#include <stdio.h>
#include <stdlib.h>

#define DEBUG 0

//#define替换文本 
#define PRINT_TEXT(TEXT) \
        printf("Hello world\t" TEXT "\tBe rich\n")

//#的使用——对于#argument的结构，预处理器解释为"argument" 
#define PRINT_CONTENT(FORMAT, CONTENT) \
        printf("The context of " #CONTENT " is " FORMAT "\n", CONTENT)

//##的使用——用于连接两个符号        
#define MERGE(NAME1, NAME2) \
        NAME1##_##NAME2
 
void function_print()
{
	printf("function print\n");
}  


//宏与函数
//宏与类型无关，而函数的参数必须声明为一种特定的类型
//这种方式与C++中模板类型自动推导有所不同
/************************************
*TABLE:#define宏与函数的不同之处
*                       #define宏                                                 函数
*代码长度：     每次使用时，宏代码都被插入到程序中         函数代码只出现在一个地方；每次都调用那个地方的同一份代码
*执行速度：               更快                                          存在函数调用/返回的额外开销
*操作符优先级：      要加括号，否则未知                       函数参数只在调用时求值一次，它的结果传递给函数
*参数求值：    参数每次用于宏定义时，都将重新求值                          函数在被调用前只求值一次。
*参数类型：            宏与类型无关                                         函数参数与类型有关。
************************************/

#define MALLOC(n, type) \
        ((type *) malloc((n) * sizeof(type))) 


//#undef移除一个宏定义
//移除DEBUG宏
#undef DEBUG
//在移除DEBUG后，可以重新define
#define DEBUG 1

//命令行定义宏
//一些C编译器可以使用选项在编译时，定义一些宏或指定宏的值

int main(int argc, char *argv[]) 
{
	#if DEBUG
		demo1:  //test PRINT_TEXT 
		{
			PRINT_TEXT("I am author");
		}
	#endif
	
	#if DEBUG
		demo2:  //test PRINT_CONTEXT
		{
			char Message[20] = "I am spiderman";
		    PRINT_CONTENT("%s", "Wo Oh");
		    PRINT_CONTENT("%s", Message);
		}
	#endif
	
	#if DEBUG
		demo3:  //test MERGE
		{
			MERGE(function, print)();
		}
	#endif
	demo4:  //test MALLOC
	{
		int * pint = MALLOC(10, int);	
	}
	
	return 0;
}